package com.cloudeasy.user.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudeasy.api.enums.ResultCodeEnum;
import com.cloudeasy.api.exception.CloudEasyException;
import com.cloudeasy.api.util.BPwdEncoderUtil;
import com.cloudeasy.api.util.SnowFlake;
import com.cloudeasy.user.constant.RoleConstant;
import com.cloudeasy.user.dto.ChangePasswordDTO;
import com.cloudeasy.user.dto.RegisterDTO;
import com.cloudeasy.user.mapper.UserMapper;
import com.cloudeasy.user.po.Permission;
import com.cloudeasy.user.po.User;
import com.cloudeasy.user.service.expand.AuthCodeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@Service
@Transactional(rollbackFor = Exception.class)
public class UserService extends ServiceImpl<UserMapper, User> {
    private final AuthCodeService authCodeService;

    private final UserInfoService userInfoService;

    private final SnowFlake snowFlake;

    public UserService(AuthCodeService authCodeService, UserInfoService userInfoService, SnowFlake snowFlake) {
        this.authCodeService = authCodeService;
        this.userInfoService = userInfoService;
        this.snowFlake = snowFlake;
    }

    /**
     * 根据账号获取账号信息
     *
     * @param account 账号
     * @return {@link User}
     */
    public User getByAccount(String account) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", account);
        User user = this.getOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new CloudEasyException(ResultCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        return user;
    }

    /**
     * 注册账号
     *
     * @param registerDTO {@link RegisterDTO}
     * @return {@link String}
     */
    public String register(RegisterDTO registerDTO) {
        // 判断账号是否存在
        if (existsAccount(registerDTO.getAccount())) {
            throw new CloudEasyException(ResultCodeEnum.ACCOUNT_EXISTS);
        }
        // 判断昵称是否存在
        if (userInfoService.existsNickname(registerDTO.getNickname())) {
            throw new CloudEasyException(ResultCodeEnum.NAME_EXISTS);
        }
        // 判断验证码是否正确
        matchesAuthCodeAndRemove(registerDTO.getAccount(), registerDTO.getAuthCode());

        String id = String.valueOf(snowFlake.nextId());
        User user = User.builder()
                .id(id)
                .account(registerDTO.getAccount())
                .password(BPwdEncoderUtil.encode(registerDTO.getPassword()))
                .build();
        // 添加账号信息，分配默认角色
        if (this.save(user) && userInfoService.save(id, registerDTO.getNickname())) {
            return id;
        }
        return null;
    }

    /**
     * 判断账号是否存在
     *
     * @param account 账号
     * @return {@link Boolean}
     */
    public Boolean existsAccount(String account) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", account);
        return this.getOne(queryWrapper) != null;
    }


    /**
     * 判断Id是否存在
     *
     * @param id Id
     * @return {@link Boolean}
     */
    public Boolean existsId(String id) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        return this.getOne(queryWrapper) != null;
    }

    /**
     * 重置密码
     *
     * @param changePasswordDTO {@link ChangePasswordDTO}
     * @return {@link Boolean}
     */
    public Boolean resetPassword(ChangePasswordDTO changePasswordDTO) {
        // 判断验证码是否正确
        matchesAuthCodeAndRemove(changePasswordDTO.getAccount(), changePasswordDTO.getAuthCode());

        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("password", BPwdEncoderUtil.encode(changePasswordDTO.getPassword()))
                .eq("account", changePasswordDTO.getAccount());
        return this.update(updateWrapper);
    }

    /**
     * 判断验证码是否正确
     * 如果正确，删除
     *
     * @param suffix   后缀
     * @param authCode 验证码
     */
    private void matchesAuthCodeAndRemove(String suffix, String authCode) {
        if (!authCodeService.matches(suffix, authCode)) {
            throw new CloudEasyException(ResultCodeEnum.VERIFICATION_CODE_ERROR);
        }
        authCodeService.remove(suffix);
    }

    /**
     * 更改用户锁定状态
     *
     * @param userId   用户Id
     * @param unlocked 目标状态
     * @return {@link Boolean}
     */
    public Boolean changeLock(String userId, Boolean unlocked) {
        User user = this.getById(userId);
        if (user == null) {
            throw new CloudEasyException(ResultCodeEnum.ID_NOT_EXISTS);
        }
        user.setUnlocked(unlocked);
        return this.updateById(user);
    }
}
